#include <cstdio>
#include <iostream>
#include <string>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <vector>

const int PORT = 8080;
const int BUFFER_SIZE = 1024;

uint8_t crc8(uint8_t *data, uint16_t length);

uint8_t crc8(uint8_t *data, uint16_t length) {
    uint8_t crc = 0; 
    while (length--) {
        crc ^= *data++;
        for (uint8_t i = 0; i < 8; i++) {
            if (crc & 0x80) {
                crc = (crc << 1) ^ 0x07;
            } else {
                crc <<= 1;
            }
        }
    }
    return crc;
}

int main() {
    int serverSocket, clientSocket;
    struct sockaddr_in serverAddr, clientAddr;
    socklen_t addrLen = sizeof(clientAddr);

    if ((serverSocket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("Socket creation error");
        return 1;
    }

    serverAddr.sin_family = AF_INET;
    serverAddr.sin_addr.s_addr = INADDR_ANY;
    serverAddr.sin_port = htons(PORT);

    if (bind(serverSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) < 0) {
        perror("Binding error");
        return 1;
    }

    if (listen(serverSocket, 5) < 0) {
        perror("Listening error");
        return 1;
    }

    std::cout << "Server listening on port " << PORT << std::endl;

    while (true) {
        if ((clientSocket = accept(serverSocket, (struct sockaddr *)&clientAddr, &addrLen) < 0)) {
            perror("Accepting error");
            return 1;
        }


        char buffer[BUFFER_SIZE];
        int bytesRead;

        while (true) {
            bytesRead = recv(clientSocket, buffer, BUFFER_SIZE, 0);
            if (bytesRead < 0) {
                perror("Receiving error");
                break;
            } else if (bytesRead == 0) {
                break;
            } else {
                std::vector<uint8_t> bufferData(buffer, buffer + bytesRead);

                if (bufferData.size() > 0) {
                    uint8_t receivedCRC = bufferData.back();
                    bufferData.pop_back();

                    uint8_t calculatedCRC = crc8(bufferData.data(), bufferData.size());
                    if (receivedCRC == calculatedCRC) {
                        std::string receivedData(bufferData.begin(), bufferData.end());
                        std::cout << "Received data: " << calculatedCRC << std::endl;

                    } else {
                                                std::cout << "Received data: " << calculatedCRC << std::endl;
                        std::cerr << "CRC8 check failed!" << std::endl;
                    }
                }
            }
        }

        close(clientSocket);
    }

    close(serverSocket);

    return 0;
}

